package org.robot.scm.platform.registry;

import static java.lang.Runtime.getRuntime;

import com.google.common.collect.Maps;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.robot.scm.platform.AbstractMonitor;
import org.robot.scm.platform.AbstractRegistry;
import org.robot.scm.pojos.enums.PlatformEnum;

/**
 * @Author : Awn create on 2024/5/12 19:36
 */
@Slf4j
public class FrpServerRegistry extends AbstractRegistry {

    private static final Map<String, Process> processMap = Maps.newHashMap();
    private static CountDownLatch latch;

    @Override
    public void registry() {
        if (!AbstractMonitor.mainConfig.getEnables().contains(PlatformEnum.FRPS.getVal())) {
            return;
        }
        try {

            Collection<File> configFiles = FileUtils.listFiles(new File("nathole/frps"), new String[]{"ini", "toml"}, false);
            latch = new CountDownLatch(configFiles.size());
            configFiles.forEach(configFile -> new Thread(() -> runFrpc(configFile, latch)).start());
            latch.await();
            processMap.keySet().forEach(configName -> getRuntime().addShutdownHook(new Thread(() -> {
                processMap.get(configName).destroyForcibly();
                log.info("{} destroy ... ok", configName);
            })));
            log.info("{} shutdown registry ... ok", processMap.size());
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    private static void runFrpc(File configFile, CountDownLatch latch) {
        try {
            Process process = getRuntime().exec("nathole/frps/frps.exe -c " + configFile.getAbsolutePath());
            processMap.put(configFile.getName(), process);
            latch.countDown();
            try (BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                String line;
                while ((line = stdoutReader.readLine()) != null) {
                    printLog(configFile.getName(), line);
                }
            }
            try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
                String line;
                while ((line = errorReader.readLine()) != null) {
                    printLog(configFile.getName(), line);
                }
            }
            process.waitFor();
        } catch (Exception e) {
            log.error("{} fail, error: {}", configFile.getName(), e.getMessage());
        }
    }

    private static void printLog(String configName, String line) {
        String logString = "";
        if (line.contains("ini format is deprecated") || line.contains("try to connect to") || line.contains("proxy added") || line.contains("login to server")) {
            return;
        }
        if (line.contains("start frps service")) {
            logString = "start frps for " + line.substring(line.lastIndexOf("["));
        }
        if (line.contains("start proxy success")) {
            logString = line.substring(line.lastIndexOf("["));
        }
        if (StringUtils.isBlank(logString)) {
            return;
        }
        log.info("{} - {}", configName, logString);
    }

}
